/******************************************************************************/
/* Serial.c												    				  */
/* Chris Day, Ying Guo	                                                      */
/******************************************************************************/
#include <stdio.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "queue.h"
#include "Serial.h"

//***** GLOBALS *****//
queue RX;
queue TX;

//***** DEFINES *****//
#define TRUE 1
#define FALSE 0

//*****************************************************************************
//
// The UART interrupt handler.
//
//*****************************************************************************
void UARTIntHandler(void) {
    unsigned long status;
	unsigned char input;

    status = UARTIntStatus(UART0_BASE, true);

    UARTIntClear(UART0_BASE, status);

    while(UARTCharsAvail(UART0_BASE)) {
		input = (unsigned char)UARTCharGetNonBlocking(UART0_BASE);
		if(input == 0x1B) {
			queue_add(&RX, input);
			input = (unsigned char)UARTCharGet(UART0_BASE);
			queue_add(&RX, input);
			input = (unsigned char)UARTCharGet(UART0_BASE);
			queue_add(&RX, input);
		} else if(input == '\r') {
			UARTCharPut(UART0_BASE, (unsigned long)'\r');
			UARTCharPut(UART0_BASE, (unsigned long)'\n');
			queue_add(&RX, input);
		} else {
			UARTCharPut(UART0_BASE, (unsigned long)input);
			queue_add(&RX, input);
		}
    }

    while((UARTSpaceAvail(UART0_BASE))&&(queue_empty(&TX) == FALSE)) {
      	UARTCharPut(UART0_BASE, (unsigned long)queue_remove(&TX));
    }	
}

//*****************************************************************************
//
// Send a integer to the UART.
//
//*****************************************************************************
void Uart_SendInt(int number) {
	char outString[10];

	sprintf(outString, "%d", number);

	Uart_SendString(outString);
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************
void Uart_SendString(char * buffer) {
	int i = 0;

    while(buffer[i] != '\0') {
        queue_add(&TX, buffer[i]);
		i++;
    }

	while((UARTSpaceAvail(UART0_BASE))&&(queue_empty(&TX) == FALSE)) {
    	UARTCharPutNonBlocking(UART0_BASE, queue_remove(&TX));
  	}
}

//*****************************************************************************
//
// Uart Initialize
//
//*****************************************************************************
void Uart_Init(void) {
	queue_init(&RX);
	queue_init(&TX);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));

	UARTEnable(UART0_BASE);
    UARTFIFOLevelSet(UART0_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8);

    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_TX | UART_INT_RX | UART_INT_RT);
}
